/*
 * Copyright (C) 2010 mAPPn.Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mol.market.common.widget;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.ConcurrentHashMap;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.TextUtils;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Checkable;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.SimpleAdapter;
import android.widget.TextView;

import com.mol.market.Constants;
import com.mol.market.R;
import com.mol.market.Session;
import com.mol.market.common.download.DownloadManager;
import com.mol.market.common.download.DownloadManager.Request;
import com.mol.market.common.network.ApiAsyncTask.ApiRequestListener;
import com.mol.market.common.network.MarketAPI;
import com.mol.market.common.util.DialogUtil;
import com.mol.market.common.util.DialogUtil.WarningDialogListener;
import com.mol.market.common.util.ImageUtils;
import com.mol.market.common.util.Utils;
import com.mol.market.common.vo.DownloadInfo;
import com.mol.market.common.vo.DownloadItem;
import com.mol.market.common.vo.UpgradeInfo;
import com.mol.market.demo.widget.LazyLoadAbsListViewFragment;
import com.mol.market.ui.LoginActivity;
import com.mol.market.ui_v4.ProductDetailActivity;

/**
 * GfanClient ListView associating adapter<br>
 * It has lazyload feature, which load data on-demand.
 * 
 * @author andrew.wang
 * 
 */
public class AppListAdapter extends BaseAdapter implements Observer, ApiRequestListener {


    private ArrayList<HashMap<String, Object>> mDataSource;

    private LazyLoadAbsListViewFragment mLazyLoadListFragment;

    private ViewBinder mViewBinder;

    private int mResource;
    private int mDividerResource;
    private boolean mHasGroup;
    private boolean mIsLazyLoad;
    private LazyloadListener mLazyloadListener;
    private String[] mFrom;
    private int[] mTo;

    private LayoutInflater mInflater;

    private Context mContext;

    private Session mSession;

    private Activity mActivity;
    private boolean mIsProductList;

    private ConcurrentHashMap<String, DownloadInfo> mDownloadingTask;

    private ConcurrentHashMap<String, UpgradeInfo> mUpdateList;

    private HashSet<String> mInstalledList;

    private DownloadManager mDownloadManager;

    private HashMap<String, HashMap<String, Object>> mDownloadExtraInfo;

    private HashMap<String, String> mIconCache;

    private HashMap<String, HashMap<String, Object>> mCheckedList;
    private boolean mIsRankList;
    private boolean mIsAllDisabled;
    private boolean mIsNeedSort;
    @SuppressWarnings("rawtypes")
    private Comparator mComparator;

    /**
     * Application list adapter<br>
     * 如果不希望这个子View显示，设置Key对应的Value为Null即可
     * 
     * @param data
     *            the dataSource behind the listView
     * @param resource
     *            list item view layout resource
     * @param from
     *            the keys array of data source which you want to bind to the
     *            view
     * @param to
     *            array of according view id
     */
    @SuppressWarnings("unchecked")
    public AppListAdapter(Context context, ArrayList<HashMap<String, Object>> data, int resource,
            String[] from, int[] to) {
        if (data == null) {
            mDataSource = new ArrayList<HashMap<String, Object>>();
        } else {
            mDataSource = data;
            if (mIsNeedSort) {
                Collections.sort(mDataSource, mComparator);
            }
        }
        mContext = context;
        mResource = resource;
        mFrom = from;
        mTo = to;
        mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mCheckedList = new HashMap<String, HashMap<String, Object>>();
        mIconCache = new HashMap<String, String>();
        mSession = Session.get(mContext);
    }

    public AppListAdapter(LazyLoadAbsListViewFragment fragment, ArrayList<HashMap<String, Object>> data,
            int resource, String[] from, int[] to) {
        if (data == null) {
            mDataSource = new ArrayList<HashMap<String, Object>>();
        } else {
            mDataSource = data;
            if (mIsNeedSort) {
                Collections.sort(mDataSource, mComparator);
            }
        }
        mContext = fragment.getActivity();
        mLazyLoadListFragment = fragment;
        mIsLazyLoad = true;
        mResource = resource;
        mFrom = from;
        mTo = to;
        mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mCheckedList = new HashMap<String, HashMap<String, Object>>();
        mIconCache = new HashMap<String, String>();
        mSession = Session.get(mContext);
    }

    /**
     * @return the mCheckedList
     */

    public HashMap<String, HashMap<String, Object>> getCheckedList() {
        return mCheckedList;
    }

    /**
     * 设置是否包含分隔项
     * 
     * @param flag
     *            默认是false, 不包含分隔符
     */
    public void setContainsPlaceHolder(boolean flag) {
        mHasGroup = flag;
    }

    /**
     * 设置分隔项的资源ID
     */
    public void setPlaceHolderResource(int id) {
        mDividerResource = id;
    }
    
    /**
     * 设置项目是否需要排序
     */
    @SuppressWarnings("rawtypes")
    public void setNeedSort(Comparator comparator) {
        mIsNeedSort = true;
        mComparator = comparator;
    }
    
    /**
     * 将产品进行重新强制排序
     */
    @SuppressWarnings("unchecked")
    public void sort() {
        Collections.sort(mDataSource, mComparator);
        notifyDataSetChanged();
    }
    
    /**
     * Sets the binder used to bind data to views.
     *
     * @param viewBinder the binder used to bind data to views, can be null to
     *        remove the existing binder
     *
     */
    public void setViewBinder(ViewBinder viewBinder) {
        mViewBinder = viewBinder;
    }

    /**
     * 排行榜，需要识别排位
     */
    public void setRankList() {
        mIsRankList = true;
    }

    /**
     * 产品列表，需要刷新产品状态
     */
    public void setProductList() {
        mIsProductList = true;
        Session session = Session.get(mContext);
        session.addObserver(this);
        mDownloadManager = session.getDownloadManager();
        mInstalledList = session.getInstalledApps();
        mDownloadingTask = session.getDownloadingList();
        mUpdateList = session.getUpdateList();
        mDownloadExtraInfo = new HashMap<String, HashMap<String, Object>>();
    }

    /**
     * 设置所有的项目不可以点击
     */
    public void setAllDisabled() {
        mIsAllDisabled = true;
    }

    /*
     * How many items are in the data set represented by this Adapter.
     */
    @Override
    public int getCount() {
        if (mDataSource == null) {
            return 0;
        }
        return mDataSource.size();
    }


    @Override
    public Object getItem(int position) {

        if (mDataSource != null && position < mDataSource.size()) {
            return mDataSource.get(position);
        }
        return null;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public boolean isEmpty() {
        if (mDataSource == null || mDataSource.size() == 0) {
            return true;
        }
        return super.isEmpty();
    }

    @Override
    public boolean areAllItemsEnabled() {
        return false;
    }

    /*
     * Clear all the data
     */
    public void clearData() {
        if (mDataSource != null) {
            mDataSource.clear();
            notifyDataSetChanged();
        }
    }
    
    /**
     * 回收资源
     */
    public void recycle() {
        clearData();
        mSession.deleteObserver(this);
        mDataSource = null;
        mActivity = null;
        mDownloadingTask = null;
        mUpdateList = null;
        mInstalledList = null;
        mDownloadManager = null;
        mDownloadExtraInfo = null;
        mIconCache = null;
        mCheckedList = null;
        mLazyLoadListFragment = null;
        mViewBinder = null;
        mInflater = null;
        mContext = null;
        mSession = null;
    }

    @Override
    public int getItemViewType(int position) {
        if (mHasGroup && isPlaceHolder(position)) {
            // place holder for group
            return 1;
        }
        // normal item
        return 0;
    }

    /*
     * Return the view types of the list adapter
     */
    @Override
    public int getViewTypeCount() {
        if (mHasGroup) {
            return 2;
        }
        return 1;
    }

    /**
     * Lazyload web data
     * 
     * @param newData
     */
    @SuppressWarnings("unchecked")
    public void addDataList(ArrayList<HashMap<String, Object>> newData) {
        if (newData != null && newData.size() > 0) {
            mDataSource.addAll(mDataSource.size(), newData);
            if (mIsNeedSort) {
                Collections.sort(mDataSource, mComparator);
            }
            notifyDataSetChanged();
        }
    }

    @SuppressWarnings("unchecked")
    public void addData(HashMap<String, Object> newData) {
        if (newData != null) {
            
            if (mIsNeedSort) {
                
                int replacePos = 0;
                boolean isReplace = false;
                for (HashMap<String, Object> item : mDataSource) {
                    String packageName = (String) item.get(Constants.KEY_PRODUCT_PACKAGE_NAME);
                    String packageNameNew = (String) newData
                            .get(Constants.KEY_PRODUCT_PACKAGE_NAME);
                    if (!TextUtils.isEmpty(packageName)
                            && packageName.equalsIgnoreCase(packageNameNew)) {
                        isReplace = true;
                        break;
                    }
                    replacePos++;
                }
                if (isReplace) {
                    mDataSource.remove(replacePos);
                }
                mDataSource.add(mDataSource.size(), newData);
                notifyDataSetInvalidated();
                Collections.sort(mDataSource, mComparator);
                return;
            }
            mDataSource.add(mDataSource.size(), newData);
            notifyDataSetChanged();
        }
    }

    public void removeData(HashMap<String, Object> oldData) {
        if (mDataSource != null) {
            mDataSource.remove(oldData);
            notifyDataSetChanged();
        }
    }
    
    public void removeDataWithPackageName(String pkgName) {
        if (mDataSource == null) {
            return;
        }
        
        int replacePos = 0;
        boolean isReplace = false;
        for (HashMap<String, Object> item : mDataSource) {
            replacePos++;
            String packageName = (String) item.get(Constants.KEY_PRODUCT_PACKAGE_NAME);
            if (!TextUtils.isEmpty(packageName)
                    && packageName.equalsIgnoreCase(pkgName)) {
                isReplace = true;
                break;
            }
        }
        if (isReplace) {
            mDataSource.remove(replacePos - 1);
        }
        notifyDataSetChanged();
    }

    public void removeData(int position) {
        if (mDataSource != null) {
            mDataSource.remove(position);
            notifyDataSetChanged();
        }
    }

    @SuppressWarnings("unchecked")
    public void insertData(HashMap<String, Object> newData) {
        if (newData != null) {
            mDataSource.add(0, newData);
            if (mIsNeedSort) {
                Collections.sort(mDataSource, mComparator);
            }
            notifyDataSetChanged();
        }
    }

    public void setLazyloadListener(LazyloadListener listener) {
        mIsLazyLoad = true;
        mLazyloadListener = listener;
    }

    @Override
    public boolean isEnabled(int position) {

        if (mIsAllDisabled) {
            return false;
        }

        if (mHasGroup) {
            return !isPlaceHolder(position);
        }
        
        return true;
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        // last 4 item trigger the lazyload event
        if (mIsLazyLoad && (position == mDataSource.size() - 4)) {
            // fix the multi-load situation
            synchronized (this) {
                if (mLazyLoadListFragment != null) {
                    mLazyLoadListFragment.doLazyLoad();
                } else if (mLazyloadListener != null) {
                    mLazyloadListener.lazyload();
                }
            }
        }

        View v;
        if (convertView == null) {
            v = newView(position, parent);
        } else {
            v = convertView;
        }
        
        if (mIsProductList && mDownloadingTask != null) {

            // 列表中存在下载列表的任务，更新状态
            HashMap<String, Object> item = mDataSource.get(position);
            String packageName = (String) item.get(Constants.KEY_PRODUCT_PACKAGE_NAME);

            if (mDownloadingTask.containsKey(packageName)) {

                DownloadInfo info = mDownloadingTask.get(packageName);
                // 下载过程中，刷新进度
                item.put(Constants.KEY_PRODUCT_INFO, info.mProgress);

                if (info.mProgressLevel == Constants.STATUS_INSTALLED) {
                    // 安装完成
                    item.put(Constants.KEY_PRODUCT_DOWNLOAD, Constants.STATUS_INSTALLED);
                    
                } else if (info.mProgressLevel == Constants.STATUS_ERROR) {
                    // 需要判断下载错误的状况
                    if (mUpdateList.containsKey(packageName)) {
                        // 恢复可更新状态
                        item.put(Constants.KEY_PRODUCT_RSA_MD5, mUpdateList.get(packageName).signature);
                        item.put(Constants.KEY_PRODUCT_DOWNLOAD, Constants.STATUS_UPDATE);
                    } else {
                        // 恢复可下载状态
                        item.put(Constants.KEY_PRODUCT_DOWNLOAD, Constants.STATUS_NORMAL);
                    }
                    
                } else if(DownloadManager.Impl.isStatusWaiting(info.mControl)) {
                    
                    // 下载队列中
                    item.put(Constants.KEY_PRODUCT_DOWNLOAD, Constants.STATUS_WAITING);
                    
                } else {
                    // 检查文件完整性，如果不存在，删除此条记录
                    if (!TextUtils.isEmpty(info.mFilePath) 
                            && (!new File(info.mFilePath).exists())) {

                        if (mUpdateList.containsKey(packageName)) {
                            // 恢复可更新状态
                            item.put(Constants.KEY_PRODUCT_RSA_MD5, mUpdateList.get(packageName).signature);
                            item.put(Constants.KEY_PRODUCT_DOWNLOAD, Constants.STATUS_UPDATE);
                        } else {
                            // 恢复可下载状态
                            item.put(Constants.KEY_PRODUCT_DOWNLOAD, Constants.STATUS_NORMAL);
                        }
                    } else {
                        item.put(Constants.KEY_PRODUCT_DOWNLOAD, info.mProgressLevel);
                    }
                    
                }

            } else if (mInstalledList.contains(packageName)) {
                
                // 已经安装的应用
                if (mUpdateList.containsKey(packageName)) {
                    // 可以更新
                    item.put(Constants.KEY_PRODUCT_DOWNLOAD, Constants.STATUS_UPDATE);
                    item.put(Constants.KEY_PRODUCT_RSA_MD5, mUpdateList.get(packageName).signature);
                    
                } else {
                    item.put(Constants.KEY_PRODUCT_DOWNLOAD, Constants.STATUS_INSTALLED);

                }
            } else {
                // 默认的状态是未安装
                item.put(Constants.KEY_PRODUCT_DOWNLOAD, Constants.STATUS_NORMAL);
            }
        }

        bindView(position, v);
        return v;
    }

    /*
     * Create new view object and cache some views associated with it
     */
    private View newView(int position, ViewGroup parent) {
        View v;
        if (mHasGroup && isPlaceHolder(position)) {
            v = mInflater.inflate(mDividerResource, parent, false);
        } else {
            v = mInflater.inflate(mResource, parent, false);
            ((ViewGroup) v).setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
        }

        final int[] to = mTo;
        final int count = to.length;
        final View[] holder = new View[count];

        for (int i = 0; i < count; i++) {
            holder[i] = v.findViewById(to[i]);
            if (R.id.cb_install == to[i]) {
                if (holder[i] != null) {
                    ((CheckBox) holder[i]).setOnCheckedChangeListener(mCheckChangeListener);
                }
            }
        }

        v.setTag(holder);
        return v;
    }

    /*
     * 装机必备安装选项
     */

    private OnCheckedChangeListener mCheckChangeListener = new OnCheckedChangeListener() {

        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            int position = (Integer) buttonView.getTag();

            HashMap<String, Object> item = (HashMap<String, Object>) mDataSource.get(position);
            item.put(Constants.INSTALL_APP_IS_CHECKED, isChecked);

            if (isChecked) {
                mCheckedList.put((String) item.get(Constants.KEY_PRODUCT_ID), item);
            } else {
                mCheckedList.remove((String) item.get(Constants.KEY_PRODUCT_ID));
            }
            buttonView.setChecked(isChecked);
        }
    };

    public void setActivity(Activity activity) {
        this.mActivity = activity;
    }

    /*
     * bind the background data to the view
     */
    private void bindView(int position, View view) {

        final HashMap<String, Object> dataSet = mDataSource.get(position);
        if (dataSet == null) {
            return;
        }

        final View[] holder = (View[]) view.getTag();
        final ViewBinder binder = mViewBinder;
        final String[] from = mFrom;
        final int[] to = mTo;
        final int count = to.length;

        for (int i = 0; i < count; i++) {

            final View v = holder[i];

            if (v != null) {

                final Object data = dataSet.get(from[i]);
                if (data == null) {
                    // make this view invisible if value is empty
                    v.setVisibility(View.GONE);
                    continue;
                }
                
                v.setVisibility(View.VISIBLE);
                
                boolean bound = false;
                if (binder != null) {
                    bound = binder.setViewValue(v, dataSet, position, data);
                }
                if (bound) {
                    continue;
                }

                if (v instanceof Checkable) {

                    // 为装机必备记录列表位置
                    v.setTag(position);
                    if (data instanceof Boolean) {
                        ((Checkable) v).setChecked((Boolean) data);
                    } else {
                        throw new IllegalStateException(v.getClass().getName()
                                + " should be bound to a Boolean, not a " + data.getClass());
                    }
                } else if (v instanceof Button) {

                    v.setTag(data);

                } else if (v instanceof ImageButton) {

                    // Note: keep the instanceof ImageButton be Top of ImageView
                    // since ImageButton is ImageView
                    // TODO setButtonImage((ImageButton) v, text);
                } else if (v instanceof ImageView) {

                    setViewImage(position, (ImageView) v, data);

                } else if (v instanceof RatingBar) {

                    setViewRating((RatingBar) v, data);

                } else if (v instanceof TextView) {

                    // Note: keep the instanceof TextView check at the bottom of
                    // these if since a lot of views are TextViews (e.g.
                    // CheckBoxes).
                    setViewText(position, (TextView) v, data);

                } else {
                    throw new IllegalStateException(v.getClass().getName() + " is not a "
                            + " view that can be bounds by this SimpleAdapter");
                }
            }
        }
    }

    /*
     * Set the value for RatingBar
     */
    private void setViewRating(RatingBar v, Object rating) {
        if (rating instanceof Float) {
            v.setRating((Float) rating);
        }
    }

    /*
     * Set text value for TextView
     */
    private void setViewText(int position, TextView v, Object text) {

        if (text instanceof byte[]) {

            v.setText(Utils.getUTF8String((byte[]) text));

        } else if (text instanceof CharSequence) {

            if (mIsRankList && v.getId() == R.id.tv_name) {
                // 排行榜
                v.setText((position + 1) + ". " + (CharSequence) text);
            } else {
                v.setText((CharSequence) text);
            }

        } else if (text instanceof Integer) {

            // 应用状态指示器
            v.setTag(position);
            final int level = (Integer) text;
            Drawable[] drawables = v.getCompoundDrawables();
            if (drawables[1] != null) {
                drawables[1].setCallback(null);
            }
            v.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.btn_downloading, 0, 0);
            Drawable indicatorDrawable = v.getCompoundDrawables()[1];
            indicatorDrawable.setLevel(level);
            if (Constants.STATUS_NORMAL == level) {
                // 未下载
                v.setText((CharSequence)mDataSource.get(position).get(Constants.KEY_PRODUCT_PRICE));
                v.setEnabled(true);
                
            } else if (Constants.STATUS_PENDING == level) {
                // 准备开始下载
                v.setText(R.string.download_status_downloading);

            } else if (Constants.STATUS_DOWNLOADED == level) {
                // 已经下载，未安装
                v.setText(R.string.download_status_downloaded);
                v.setEnabled(true);

            } else if (Constants.STATUS_INSTALLED == level) {
                // 已经安装
                if (mIsNeedSort) {
                    v.setText(R.string.operation_uninstall);
                    v.setCompoundDrawablesWithIntrinsicBounds(null, mContext.getResources()
                            .getDrawable(R.drawable.btn_uninstall), null, null);
                } else {
                    v.setText(R.string.download_status_installed);
                }
                v.setEnabled(true);
                
            } else if (Constants.STATUS_UPDATE == level) {
                // 有更新
                v.setText(R.string.operation_update);
                v.setEnabled(true);

            } else if (Constants.STATUS_WAITING == level) {
                
                v.setText(R.string.label_start_short);
                v.setEnabled(true);
                
            } else {
                // 下载中
                v.setText((String) mDataSource.get(position).get(Constants.KEY_PRODUCT_INFO));

            }
            // 为下载按钮绑定事件
            v.setOnClickListener(mDownloadListener);
        }
    }

    /*
     * Set drawable value for ImageView
     */
    private void setViewImage(int position, ImageView v, Object obj) {

        Drawable oldDrawable = v.getDrawable();
        if (oldDrawable != null) {
            // clear the CALLBACK reference to prevent of OOM error
            oldDrawable.setCallback(null);
        }

        if (obj instanceof Drawable) {
            // here is one drawable object
            v.setImageDrawable((Drawable) obj);

        } else if (obj instanceof String) {
            // here is one remote object (URL)
            if (v.getId() == R.id.iv_user_icon) {
                ImageUtils.download(mContext, (String) obj, v,
                    R.drawable.default_user_big, false, false);
            } else {
                ImageUtils.download(mContext, (String) obj, v, false);
            }
            
        } else if (obj instanceof Boolean) {

            if ((Boolean) obj) {
                v.setVisibility(View.VISIBLE);
            } else {
                v.setVisibility(View.INVISIBLE);
            }
        } else if (obj instanceof PackageInfo) {

            ImageUtils.download(mContext, ((PackageInfo) obj).packageName, v,
                    R.drawable.loading_icon);

        }
    }


    private OnClickListener mDownloadListener = new OnClickListener() {

        @Override
        public void onClick(final View v) {

            int position = (Integer) v.getTag();
            final HashMap<String, Object> item = mDataSource.get(position);
            int status = (Integer) item.get(Constants.KEY_PRODUCT_DOWNLOAD);
            int payType = 1;
            Object tempValue = item.get(Constants.KEY_PRODUCT_PAY_TYPE);
            if (tempValue != null) {
                payType = (Integer) tempValue;
            }

            if (Constants.STATUS_DOWNLOADING == status) {

                // 下载中，点击暂停下载
                String packageName = (String) item.get(Constants.KEY_PRODUCT_PACKAGE_NAME);
                DownloadInfo info = mDownloadingTask.get(packageName);
                if (info != null) {
                  mDownloadManager.pauseDownload(info.id);
                }

            } else if (Constants.STATUS_WAITING == status) {
                
                // 下载队列中，恢复下载
                String packageName = (String) item.get(Constants.KEY_PRODUCT_PACKAGE_NAME);
                DownloadInfo info = mDownloadingTask.get(packageName);
                if (info != null) {
                    mDownloadManager.resumeDownload(info.id);
                }
                
            } else if (Constants.STATUS_NORMAL == status || Constants.STATUS_UPDATE == status) {

                if (mIsNeedSort) {
                    Utils.trackEvent(mContext, Constants.GROUP_7, Constants.CLICK_UPDATE);
                }
                v.setEnabled(false);

                if (Constants.PAY_TYPE_PAID == payType) {
                    if (Session.get(mContext).isLogin()) {
                        Intent intent = new Intent(mContext, ProductDetailActivity.class);
                        intent.putExtra(Constants.EXTRA_PRODUCT_ID,
                                (String) item.get(Constants.KEY_PRODUCT_ID));
                        intent.putExtra(Constants.IS_BUY, true);
                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        mContext.startActivity(intent);
                    } else {
                        Intent loginIntent = new Intent(mContext, LoginActivity.class);
                        loginIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        mContext.startActivity(loginIntent);
                    }
                } else {
                    
                    if (Constants.STATUS_UPDATE == status) {
                        String md5 = (String) item.get(Constants.KEY_PRODUCT_RSA_MD5);
                        String pkgName = (String) item.get(Constants.KEY_PRODUCT_PACKAGE_NAME);
                        if (!Utils.isSameSign(mContext, pkgName, md5)) {
                            
                            if (!mActivity.isFinishing()) {
                                DialogUtil.createComfirmDownloadDialog(mActivity, true,
                                        new WarningDialogListener() {

                                            @Override
                                            public void onWarningDialogOK(int id) {
                                                startDownload(item);
                                            }

                                            @Override
                                            public void onWarningDialogCancel(int id) {
                                            }

                                        }).show();
                            }
                            return;
                        }
                    }
                    startDownload(item);
                }
                v.setEnabled(true);

            } else if (Constants.STATUS_DOWNLOADED == status) {

                // 安装应用
                final String packageName = (String) item.get(Constants.KEY_PRODUCT_PACKAGE_NAME);
                String filePath = (String) item.get(Constants.KEY_PRODUCT_INFO);
                DownloadInfo info = mDownloadingTask.get(packageName);
                if (info != null) {
                    filePath = info.mFilePath;
                }

                if (!TextUtils.isEmpty(filePath)) {
                    if (Utils.compareFileWithPathAndPkg(mContext, filePath, packageName)) {
                        Utils.installApk(mContext, new File(filePath));
                        return;
                    }
                    final String path = filePath;
                    DialogUtil.createComfirmDownloadDialog(mActivity, false,
                            new WarningDialogListener() {

                                @Override
                                public void onWarningDialogOK(int id) {
                                    mSession.mNotSameApps.put(packageName, path);
                                    Utils.uninstallApk(mContext, packageName);
                                }

                                @Override
                                public void onWarningDialogCancel(int id) {
                                }

                            }).show();
                }
            } else if (Constants.STATUS_INSTALLED == status) {

                if (mIsNeedSort) {
                    
                    Utils.trackEvent(mContext, Constants.GROUP_7,
                            Constants.CLICK_UNINSTALL);
                    String packageName = (String) item.get(Constants.KEY_PRODUCT_PACKAGE_NAME);
                    Utils.uninstallApk(mContext, packageName);
                } else {
                    // 已经安装，打开应用
                    String packageName = (String) item.get(Constants.KEY_PRODUCT_PACKAGE_NAME);
                    Utils.openApk(mActivity, packageName);
                }
            }
        }
    };
    
    public void updateAll() {

        if (mDataSource == null) {
            return;
        }
        
        if (mUpdateList == null) {
            mUpdateList = mSession.getUpdateList();
        }
        
        for (HashMap<String, Object> item : mDataSource) {

            Object value = item.get(Constants.KEY_PRODUCT_PACKAGE_NAME);
            String pkgName = null;
            if (value != null && (value instanceof String)) {
                pkgName = (String) value;
            } else {
                // 非法项目
                continue;
            }
            
            if (!mUpdateList.containsKey(pkgName)) {
                // 不是可更新项目
                continue;
            }

            UpgradeInfo upgrade = mUpdateList.get(pkgName);
            if (!TextUtils.isEmpty(upgrade.filePath) && new File(upgrade.filePath).exists()) {
                // 已经下载完成
                continue;
            }

            if (mDownloadingTask != null && mDownloadingTask.containsKey(pkgName)) {
                // 已经存在于下载任务中
                DownloadInfo download = mDownloadingTask.get(pkgName);
                if (DownloadManager.Impl.isStatusRunning(download.mStatus)) {
                    continue;
                }
            }
            // 开始更新
            startDownload(item);
        }
    }

    private void startDownload(HashMap<String, Object> item) {
        // 避免网络无效
        if (!Utils.isNetworkAvailable(mContext)) {
            Utils.makeEventToast(mContext, mContext.getString(R.string.no_data), false);
            return;
        }
        
        if (mSession.addDownload(item.get(Constants.KEY_PRODUCT_PACKAGE_NAME))) {
            String pkgName = (String) item.get(Constants.KEY_PRODUCT_PACKAGE_NAME);
            String pid = (String) item.get(Constants.KEY_PRODUCT_ID);
            String iconUrl = (String) item.get(Constants.KEY_PRODUCT_ICON_URL);
            String sourceType = (String) item.get(Constants.KEY_PRODUCT_SOURCE_TYPE);
            item.put(Constants.KEY_PRODUCT_DOWNLOAD, Constants.STATUS_PENDING);
            mIconCache.put(pkgName, iconUrl);
            MarketAPI.getDownloadUrl(mContext, AppListAdapter.this,
                    pid, sourceType, pkgName);
            mDownloadExtraInfo.put(pid, item);
            notifyDataSetChanged();
        }
    }

    @Override
    public void onSuccess(int method, Object obj) {
        
        if (mSession == null) {
            return;
        }
        
        switch (method) {
        case MarketAPI.ACTION_GET_DOWNLOAD_URL:

            DownloadItem info = (DownloadItem) obj;

            HashMap<String, Object> downloadItem = mDownloadExtraInfo.get(info.pId);
            Request request = new Request(Uri.parse(info.url));
            request.setTitle((String) downloadItem.get(Constants.KEY_PRODUCT_NAME));
            request.setPackageName(info.packageName);
            request.setIconUrl(mIconCache.get(info.packageName));
            request.setSourceType(com.mol.market.common.download.Constants.DOWNLOAD_FROM_MARKET);
            request.setMD5(info.fileMD5);
            mDownloadManager.enqueue(mContext, request, null);
            Utils.makeEventToast(mContext, mContext.getString(R.string.download_start), false);
            break;

        default:
            break;
        }
    }

    @Override
    public void onError(int method, int statusCode) {
        
        if (mSession == null) {
            return;
        }
        
        Utils.makeEventToast(mContext, mContext.getString(R.string.alert_dialog_error), false);
    }

    /**
     * 下载状态更新，刷新列表状态
     */
    @SuppressWarnings("unchecked")
    @Override
    public void update(Observable arg0, Object arg1) {

        if (arg1 instanceof ConcurrentHashMap) {
            mDownloadingTask = (ConcurrentHashMap<String, DownloadInfo>) arg1;
            notifyDataSetChanged();
        } else if (arg1 instanceof Integer) {
            
            int code = (Integer) arg1;
            if (code == Constants.INFO_INSTALL_CHANGED) {
                mInstalledList = mSession.getInstalledApps();
            }
            
            notifyDataSetChanged();
        }
    }

    /*
     * 是否分隔符
     */
    private boolean isPlaceHolder(int position) {
        HashMap<String, Object> item = mDataSource.get(position);
        Object value = item.get(Constants.KEY_PLACEHOLDER);
        if (value == null) {
            return false;
        }
        return (Boolean) value;
    }
    
    /**
     * This class can be used by external clients of SimpleAdapter to bind
     * values to views.
     *
     * You should use this class to bind values to views that are not
     * directly supported by SimpleAdapter or to change the way binding
     * occurs for views supported by SimpleAdapter.
     *
     * @see SimpleAdapter#setViewImage(ImageView, int)
     * @see SimpleAdapter#setViewImage(ImageView, String)
     * @see SimpleAdapter#setViewText(TextView, String)
     */
    public static interface ViewBinder {
        /**
         * Binds the specified data to the specified view.
         *
         * When binding is handled by this ViewBinder, this method must return true.
         * If this method returns false, SimpleAdapter will attempts to handle
         * the binding on its own.
         *
         * @param view the view to bind the data to
         * @param data the data to bind to the view
         * @param textRepresentation a safe String representation of the supplied data:
         *        it is either the result of data.toString() or an empty String but it
         *        is never null
         *
         * @return true if the data was bound to the view, false otherwise
         */
        boolean setViewValue(View view, Object data, int position, Object textRepresentation);
    }

    /**
     * Lazyload linstener If you want use the lazyload function, must implements
     * this interface
     */
    public interface LazyloadListener {

        /**
         * You should implements this method to justify whether should do
         * lazyload
         *
         * @return
         */
        boolean isEnd();

        /**
         * Do something that process lazyload
         */
        void lazyload();

        /**
         * Indicate whether the loading process is over
         *
         * @return
         */
        boolean isLoadOver();
    }

    //********************* injection ********************
    private SparseArray<OnClickListener> mInjectionPoller = new SparseArray<View.OnClickListener>();

    public void injection(int id, View.OnClickListener what,boolean remove) {
        if(remove){
            mInjectionPoller.remove(id);
        }else{
            mInjectionPoller.put(id, what);
        }
    }

    private void setInjection(View v){

        int id = v.getId();

        if(id == 0){
            //默认Id，不需要注入
            return ;
        }
        if(mInjectionPoller.get(id) != null){
//            v.setOnClickListener(this);
        }
    }

    //********************* injection end ********************

    public void onClick(View v) {
        View.OnClickListener injectionListener = mInjectionPoller.get(v.getId());
        boolean isInjection = (injectionListener != null);

        if(isInjection){
            injectionListener.onClick(v);
        }
    }

}